use crate::models::order_payments::{self, CreateParams};
use axum::{
    Json, Router,
    extract::State,
    routing::{get, post},
};
use loco_rs::prelude::*;
use serde::Deserialize;

pub fn routes() -> Router<AppContext> {
    Router::new()
        .route("/order-payments", post(create))
        .route("/order-payments/:id", get(get_by_id))
        .route("/order-payments/:id/paid", post(update_paid_status))
        .route("/order-payments/:id/reference", post(update_reference))
        .route("/order-payments/by-order/:order_id", get(get_by_order))
}

async fn create(
    State(state): State<AppContext>,
    Json(params): Json<CreateParams>,
) -> Result<Response> {
    let order_payment = order_payments::Model::create(&state.db, &params).await?;
    format::json(order_payment)
}

async fn get_by_id(
    State(state): State<AppContext>,
    axum::extract::Path(id): axum::extract::Path<String>,
) -> Result<Response> {
    let order_payment = order_payments::Model::find_by_id(&state.db, &id).await?;
    format::json(order_payment)
}

#[derive(Debug, Deserialize)]
pub struct UpdatePaidStatusParams {
    pub paid: bool,
}

async fn update_paid_status(
    State(state): State<AppContext>,
    axum::extract::Path(id): axum::extract::Path<String>,
    Json(params): Json<UpdatePaidStatusParams>,
) -> Result<Response> {
    let order_payment = order_payments::Model::find_by_id(&state.db, &id).await?;
    let active_model: order_payments::ActiveModel = order_payment.into();
    let updated_payment = active_model
        .update_paid_status(&state.db, params.paid)
        .await?;
    format::json(updated_payment)
}

#[derive(Debug, Deserialize)]
pub struct UpdateReferenceParams {
    pub reference: Option<String>,
}

async fn update_reference(
    State(state): State<AppContext>,
    axum::extract::Path(id): axum::extract::Path<String>,
    Json(params): Json<UpdateReferenceParams>,
) -> Result<Response> {
    let order_payment = order_payments::Model::find_by_id(&state.db, &id).await?;
    let active_model: order_payments::ActiveModel = order_payment.into();
    let updated_payment = active_model
        .update_reference(&state.db, params.reference)
        .await?;
    format::json(updated_payment)
}

async fn get_by_order(
    State(state): State<AppContext>,
    axum::extract::Path(order_id): axum::extract::Path<String>,
) -> Result<Response> {
    let order_payments = order_payments::Model::find_by_order_id(&state.db, &order_id).await?;
    format::json(order_payments)
}
